﻿using Abp.Application.Services.Dto;
using Abp.AutoMapper;
using Abp.Domain.Repositories;
using Abp.Domain.Uow;
using Abp.Linq.Extensions;
using Hicap.AuthorizationServer.CommonDto;
using Hicap.AuthorizationServer.Core.Caches.Sys;
using Hicap.AuthorizationServer.Core.Caches.Sys.Interface;
using Hicap.AuthorizationServer.Core.Models.Sys;
using Hicap.AuthorizationServer.Sys.AppService.Interface;
using Hicap.AuthorizationServer.Sys.DTO.AuthObjects;
using Hicap.AuthorizationServer.Sys.DTO.Roles;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Dynamic.Core;
using System.Linq.Expressions;
using System.Threading.Tasks;

namespace Hicap.AuthorizationServer.Sys.AppService
{
    /// <summary>
    /// Role应用层服务的接口实现方法
    /// </summary>
    public class RoleAppService
        : AuthorizationServerAppServiceBase<Role, RoleAppService, RoleEditDto, RoleListDto, RoleCacheItem>, IRoleAppService
    {
        ////BCC/ BEGIN CUSTOM CODE SECTION
        ////ECC/ END CUSTOM CODE SECTION
        private readonly IRepository<AuthObjectRoleRelated> _authRoleRepository;

        private readonly IRepository<Role> _roleRepository;
        private readonly IUnitOfWorkManager _unitOfWorkManager;

        /// <summary>
        /// 构造函数
        /// </summary>
        public RoleAppService(IRepository<Role> roleRepository,
            IUnitOfWorkManager unitOfWorkManager,
            IRepository<AuthObjectRoleRelated> authRoleRepository,
            IRoleCache cache)
            : base(
                roleRepository,
                unitOfWorkManager,
                cache)
        {
            _unitOfWorkManager = unitOfWorkManager;
            _authRoleRepository = authRoleRepository;
            _roleRepository = roleRepository;
            ForeignKeys.Add(x => x.Parent);
            CreateActions.Add(SetParent);
            UpdateActions.Add(SetParentId);
        }

        /// <summary>
        /// 获取User的分页列表信息
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public override async Task<PagedResultDto<RoleListDto>> PagedDatas(QueryInput input)
        {
            //            PermissionCheck();

            IQueryable<Role> query = GetQuery(input);

            int roleCount = await query.CountAsync();

            List<Role> roles;
            //            if (IsInitUser())
            //            {
            //                using (_unitOfWorkManager.Current.DisableFilter(AbpDataFilters.MayHaveTenant))
            //                {
            //                    roles = await query
            //                      .OrderBy(input.Sorting)
            //                      .PageBy(input)
            //                      .ToListAsync();
            //                }
            //            }
            //            else
            //            {
            roles = await query
               .OrderBy(input.Sorting)
               .PageBy(input)
               .ToListAsync();
            //            }

            List<RoleListDto> roleListDtos = roles.MapTo<List<RoleListDto>>();
            foreach (RoleListDto roleListDto in roleListDtos)
            {
                List<Expression<Func<AuthObjectRoleRelated, dynamic>>> keys = new List<Expression<Func<AuthObjectRoleRelated, dynamic>>>()
          {
              x => x.AuthObject,
              x => x.Role
          };

                foreach (AuthObjectRoleRelated authObjectRoleRelated in _authRoleRepository
                    .GetAllIncluding(keys.ToArray())
                    .Where(y => y.Role.Id == roleListDto.Id))
                {
                    AuthObject auth = authObjectRoleRelated.AuthObject;
                    AuthObjectListDto map = auth.MapTo<AuthObjectListDto>();
                    map.AuthRoleReleatedId = authObjectRoleRelated.Id;
                    roleListDto.AuthObject.Add(map);
                }
            }

            return new PagedResultDto<RoleListDto>(
                roleCount,
                roleListDtos
            );
        }

        private void SetParentId(RoleEditDto input, Role dbEntity)
        {
            if (input.ParentRoleId.HasValue) dbEntity.Parent.Id = input.ParentRoleId.Value;
        }

        private void SetParent(RoleEditDto input, Role entity)
        {
            if (input.ParentRoleId.HasValue)
            {
                //                var cache = await _roleCache.GetAsync(input.ParentRoleId.Value);
                //                var parent = cache.MapTo<Role>();
                //                entity.Parent = _roleRepository.GetDbContext().Attach(parent).Entity;
                entity.Parent = _roleRepository.Get(input.ParentRoleId.Value);
            }
        }
    }
}